﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Models.Common;
using Models.Device;
using Models.Task;
using Nancy.TinyIoc;
using Newtonsoft.Json;
using GateWayCommonService.CloudCenter;

using GateWayCommonService.Device;

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Data;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using Utils_ORM;
using Utils_ORM.MySql_IotWork;
using static Models.Common.EnumDeviceState;
using GateWayCommonService.Data;
using Utils_Redis;

namespace GateWayCommonService.CloudCenter
{
    /// <summary>
    /// 计划任务、流程步骤执行
    /// </summary>
    public class ServiceTaskPlain_Bak
    {

        public void taskRun()
        {
            Task.Run(() =>
            {

                while (true)
                {
                    try
                    {
                        DataEFContext ef = new DataEFContext();
                        //当多节点时，同时只有一处执行
                        List<iot_device_task_plain> task_PlainList = ef.iot_device_task_plain.Where(c => c.tp_status == 0 && c.tp_complete==0).ToList();
                        foreach (iot_device_task_plain item in task_PlainList)
                        {
                            getTaskPlianTask(item.tp_guid);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                    Thread.Sleep(1000);
                }
            });
        }
        /// <summary>
        /// 处理条件流程队列
        /// </summary>
        public void getTaskPlianTask(string tpguid = "")
        {
            if (tpguid == "6e83cc7b-0837-42b3-8f96-007160fe9925")
            {
                ServiceDeviceSensorWaterFlowPulse1019.staticpulse = 0;
            }
            if (new UtilRedisHelper().Lock("getTaskPlianTask" + tpguid))//避免上一次还没运行完，又到定时，运行一次相同的流程
            {
                DataEFContext ef = new DataEFContext();

                iot_device_task_plain task_Plain = ef.iot_device_task_plain.Where(c => c.tp_status == 0 && c.tp_guid == tpguid).FirstOrDefault();
                if (task_Plain == null)
                {
                    return;
                }
                //if (task_Plain.tp_complete == 0 && task_Plain.tp_set_live_time > DateTime.Now.AddMinutes(-1))
                //{
                //    //流程正在处理中，避免重复处理，退出
                //    return;
                //}

                //if (task_Plain.tp_complete == 1)
                //{

                //判断设备是否在线，不在线的话，就不执行了

                List<iot_device_task_plain_item> plain_Items = ef.iot_device_task_plain_item.Where(c => c.tpi_tp_guid == task_Plain.tp_guid && c.tpi_status == 0).ToList();
                //bool isPass = checkAllVaild(task_Plain, plain_Items);
                //if (isPass == false)
                //{//检测不通过

                //   // return;
                //}

                //以下通过检测，可以运行

                string sqlupd1 = "update iot_device_task_plain set " +
                       " tp_execute_batch_no='" + DateTime.Now.ToString("yyyyMMddHHmmss") + "'," +
                       " tp_execute_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "'," +
                       " tp_complete= 0 " +
                       " where tp_guid='" + task_Plain.tp_guid + "' and tp_complete=1";
                int resultcount = new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd1);
                if (resultcount > 0)
                {
                    foreach (iot_device_task_plain_item item in plain_Items)
                    {
                        string sqlupd2 = "update iot_device_task_plain_item set " +
                              " tpi_execute_batch_no=''," +
                           " tpi_complete=0," +
                           " tpi_execute_delayed_time=null," +
                           " tpi_execute_time= null," +
                            " tpi_complete_time=null " +
                           " where tpi_guid='" + item.tpi_guid + "'";
                        new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd2);
                    }
                }
                //}
                //else if (task_Plain.tp_complete == 0 && task_Plain.tp_set_live_time > DateTime.Now.AddMinutes(-1))
                //{
                //    //流程正在处理中，避免重复处理，退出
                //    return;
                //}

                //循环处理子流程

                //while (true)
                //{
                //ef = new DataEFContext();
                // task_Plain = ef.iot_device_task_plain.Where(c => c.tp_guid == tpguid).FirstOrDefault();
                // if (task_Plain.tp_complete == 1)
                // {//处理完成，退出
                //     break;
                // }
                //string sqlupd = "update iot_device_task_plain set tp_set_live_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' where tp_guid='" + task_Plain.tp_guid + "'";
                //new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);


                 action(task_Plain);
               

                //bool itemIsPass = checkAllVaild(task_Plain, plain_Items);
                //if (itemIsPass == false)
                //{//检测不通过

                //    // break;
                //}
                ef.Dispose();
               // Thread.Sleep(100);
                // }

                ef.Dispose();
                new UtilRedisHelper().DelLock("getTaskPlianTask" + tpguid);
            }

        }

        /// <summary>
        /// 根据传感器回传信息时调用，考虑是否调用过于频繁
        /// </summary>
        /// <param name="deviceGuid"></param>
        public void action(iot_device_task_plain task_Plain)
        {
            try
            {

                DataEFContext ef = new DataEFContext();

                iot_device_task_plain_item item = ef.iot_device_task_plain_item.Where(c => c.tpi_tp_guid == task_Plain.tp_guid && c.tpi_status == 0 && c.tpi_complete == 0).OrderBy(c => c.tpi_order).Take(1).FirstOrDefault();
                if (item == null)
                {
                    //已经全部处理完成
                    //更新主单状态
                    string sqlupd = "update iot_device_task_plain set tp_complete=1,tp_set_live_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' where tp_guid='" + task_Plain.tp_guid + "'";
                    new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);

                    new TaskPlainLog().addTaskPlianTaskLog(task_Plain, 0, "正常");
                    return;
                }
                else if (item.tpi_execute_time == null)
                {
                    string sqlupd = "update iot_device_task_plain_item set tpi_execute_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' where tpi_guid='" + item.tpi_guid + "'";
                    new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);
                }

                Console.WriteLine("流程处理-->" + item.tpi_title);
                //判断处理方式,

                if (item.tpi_type == 0)
                {
                    //0指令
                    iot_device device = new ServiceIotDeviceCache().getClientDeviceByCache(item.tpi_taskobj_guid);// new RedisHelper().StringGet<List<iot_device>>("devicelist").Where(c => c.d_guid == item.tpi_taskobj_guid).FirstOrDefault();

                    iot_device_command iot_Device_Command = new ServiceIotDeviceCommandCache().getCommandByCache(device.d_model_guid, item.tpi_key);


                    string commandGuid = new ServiceDeviceCommand().sendCommandToGateWay(device.d_guid, item.tpi_key, "流程任务 tpi_id:" + item.tpi_id.ToString());



                    string sqlupd1 = "update iot_device_task_plain_item set tpi_execute_batch_no='" + task_Plain.tp_execute_batch_no + "'," +
                        " tpi_complete=1," +
                        " tpi_object_guid='" + commandGuid + "'," +
                        " tpi_object_type= 'commandlog'," +
                         " tpi_complete_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' " +
                        " where tpi_guid='" + item.tpi_guid + "'";
                    new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd1);

                    //结束等待
                    new TaskPlainLog().addTaskPlianTaskLogItem(item, 0, "正常");
                  //  return true;

                    action(task_Plain);//马上执行下一条
                }
                else if (item.tpi_type == 1)
                {
                    //1条件,写批号到iot_device_command_Processing，没有记录，表示已经执行完

                    //iot_device_linkage linkage = ef.iot_device_linkage.Where(c => c.l_guid == task_Plain.tp_guid).FirstOrDefault();
                    //new ServiceDeviceLinkageCondition().insertExecuteRecordHandRun(linkage.l_guid);
                    //等待完成，怎么等？，传批次号进去？
                }
                else if (item.tpi_type == 2)
                {

                    //2条件是否成立，成立就通过，不成立就停在这里，如温度多少，ec值多少，ph多少，才进行下一步
                    iot_device_value_current iot_Device_Value_Current = ef.iot_device_value_current.Where(c => c.vc_d_guid == item.tpi_taskobj_guid).FirstOrDefault();
                    if (iot_Device_Value_Current != null)
                    {
                        if (item.tpi_value_rlue == ">")
                        {
                            if (!(double.Parse(iot_Device_Value_Current.vc_value) > double.Parse(item.tpi_value)))
                            {
                                //不成立，运行条件
                            }
                            else
                            {
                                //结束等待

                                string sqlupd = "update iot_device_task_plain_item set tpi_execute_batch_no='" + task_Plain.tp_execute_batch_no + "'," +
                       " tpi_complete=1," +
                        " tpi_complete_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' " +
                       " where tpi_guid='" + item.tpi_guid + "'";
                                new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);


                                new TaskPlainLog().addTaskPlianTaskLogItem(item, 0, "正常");
                                //   break;
                            }
                        }
                        else if (item.tpi_value_rlue == "<")
                        {
                            if (!(double.Parse(iot_Device_Value_Current.vc_value) < double.Parse(item.tpi_value)))
                            {
                                //不成立，运行条件
                                //iot_device_linkage linkage = ef.iot_device_linkage.Where(c => c.l_guid == item.tpi_object_guid).FirstOrDefault();
                                //if (linkage != null)
                                //{
                                //    new ServiceDeviceLinkageCondition().insertExecuteRecordHandRun(linkage.l_guid);
                                //}
                            }
                            else
                            { //结束等待


                                string sqlupd = "update iot_device_task_plain_item set tpi_execute_batch_no='" + task_Plain.tp_execute_batch_no + "'," +
                       " tpi_complete=1," +
                        " tpi_complete_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' " +
                       " where tpi_guid='" + item.tpi_guid + "'";
                                new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);

                                new TaskPlainLog().addTaskPlianTaskLogItem(item, 0, "正常");
                                //  break;


                                action(task_Plain);//马上执行下一条
                            }
                        }
                        // }
                        //等待完成，怎么等？，传批次号进去？
                        //Thread.Sleep(1000);
                    }
                    else
                    {
                        //处理错误
                        new TaskPlainLog().addTaskPlianTaskLogItem(item, 1, "设备数据 不存在");
                        new TaskPlainLog().addTaskPlianTaskLog(task_Plain, 1, "任务运行失败");
                      //  return false;
                    }
                }
                else if (item.tpi_type == 100)
                {//延时间
                 //查上一个处理完成时间 加上当前时间

                    if (item.tpi_execute_batch_no != task_Plain.tp_execute_batch_no)
                    {


                        string sqlupd2 = "update iot_device_task_plain_item set tpi_execute_batch_no='" + task_Plain.tp_execute_batch_no + "'," +
               " tpi_execute_delayed_time='" + DateTime.Now.AddSeconds(double.Parse(item.tpi_value)).ToString("yyyy-MM-dd HH:mm:ss") + "' " +
               " where tpi_guid='" + item.tpi_guid + "'";
                        new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd2);

                        item.tpi_execute_delayed_time = DateTime.Now.AddSeconds(double.Parse(item.tpi_value));

                        new TaskPlainLog().addTaskPlianTaskLogItem(item, 0, "正常");
                    }
                    //if (item.tpi_execute_delayed_time > DateTime.Now)
                    //{
                    //    int sleepSecond = new UtilsDateTime().getTimeCompare(DateTime.Now, (DateTime)item.tpi_execute_delayed_time, "ss");

                    //    //这里是为了保持tp_set_live_time 1分钟内的心跳刷新时间，sleep不存过1分钟                        
                    //    if (sleepSecond > 50)
                    //    {
                    //        Thread.Sleep(50 * 1000);//等待执行时间
                    //    }
                    //    else
                    //    {
                    //        Thread.Sleep(sleepSecond * 1000);//等待执行时间
                    //    }
                    //}

                    //if (item.tpi_execute_delayed_time > DateTime.Now)
                    //{
                    //    //还没到执行时间
                    //    return;
                    //}
                    //else
                    //{
                    //结束等待
                    if (item.tpi_execute_delayed_time < DateTime.Now)
                    {
                        string sqlupd = "update iot_device_task_plain_item set tpi_execute_batch_no='" + task_Plain.tp_execute_batch_no + "'," +
                  " tpi_complete=1," +
                   " tpi_complete_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' " +
                  " where tpi_guid='" + item.tpi_guid + "'";
                        new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);


                        new TaskPlainLog().addTaskPlianTaskLogItem(item, 0, "正常");

                        action(task_Plain);//马上执行下一条
                    }
                    // }
                  //  return true;
                }
                else if (item.tpi_type == 3)
                {  //传感器上传数据
                   //判断上一步tpi_complete=1是否已经处理，论到自己处理没有
                    //iot_device_task_plain_item parentItem = ef.iot_device_task_plain_item.Where(c => c.tpi_tp_guid == item.tpi_tp_guid && c.tpi_status == 0 && c.tpi_order < item.tpi_order && c.tpi_complete == 0).FirstOrDefault();
                    //if (parentItem != null)
                    //{
                    //    //跳过
                    //    return true;
                    //}


                    iot_device device = new ServiceIotDeviceCache().getClientDeviceByCache(item.tpi_taskobj_guid);
                    iot_device_command commamditem = new ServiceIotDeviceCommandCache().getCommandByCache(device.d_model_guid, item.tpi_key);
                    // List<iot_device_command> commandslist = ef.iot_device_command.Where(c => c.dc_model_guid == device.d_model_guid && c.dc_status == 0 && c.dc_key == item.tpi_key).ToList();
                    //  foreach (iot_device_command commamditem in commandslist)
                    // {
                    new ServiceDeviceCommand().sendCommandToGateWay(item.tpi_taskobj_guid, commamditem.dc_key, "流程任务 tpi_id:" + item.tpi_id, "", (int)item.tpi_repeat_count, (int)item.tpi_repeat_interval);
                    //  }
                    //更新


                    string sqlupd = "update iot_device_task_plain_item set " +
                      "   tpi_execute_batch_no = '" + task_Plain.tp_execute_batch_no + "'," +
                  " tpi_complete=1," +
                    " tpi_execute_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "', " +
                   " tpi_complete_time='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' " +
                  " where tpi_guid='" + item.tpi_guid + "'";
                    new UtilsMySql().Db.Ado.ExecuteCommand(sqlupd);
                    new TaskPlainLog().addTaskPlianTaskLogItem(item, 0, "正常");
                    action(task_Plain);//马上执行下一条
                }
               // return true;
            }
            catch (Exception ex)
            {

                Console.WriteLine("  LinkageCondition -----error-------" + ex);
                new ServiceSystemLogError().addSystemLogError("流程处理失败，tp_guid:" + task_Plain.tp_guid, ex.ToString());
                //return false;
            }

        }
        /// <summary>
        ///检测有效性
        /// </summary>
        /// <param name="plain_Items"></param>
        /// <returns></returns>
        protected bool checkAllVaild(iot_device_task_plain plain, List<iot_device_task_plain_item> plain_Items)
        {
            DataEFContext ef = new DataEFContext();
            bool isPass = true;
            DateTime dtOnline = DateTime.Now.AddMinutes(-2);

            foreach (iot_device_task_plain_item item in plain_Items.Where(c => c.tpi_type == 0 || c.tpi_type == 3).ToList())
            {
                iot_device device = new ServiceIotDeviceCache().getClientDeviceByCache(item.tpi_taskobj_guid); //ef.iot_device.Where(c => c.d_guid == item.tpi_taskobj_guid).FirstOrDefault();
                if (device == null)
                {
                    isPass = false;
                    new TaskPlainLog().addTaskPlianTaskLogItem(item, 1, "设备 不存在");
                    break;
                }


                //判断设备异常问题
                iot_device_live_state device_State = ef.iot_device_live_state.Where(c => c.ls_d_guid == device.d_guid).FirstOrDefault();
                if (device_State != null && (device_State.ls_live_state == 2 || device_State.ls_live_state == 3))
                {
                    isPass = false;
                    new TaskPlainLog().addTaskPlianTaskLogItem(item, 1, "设备“" + device.d_name + "”异常");
                    //return isPass;
                    break;
                }


                //判断网关在线
                iot_device_live_state live_State = new ServiceIotDeviceLiveStateCache().getGateWayIsOnlineByCache(device.d_gw_d_guid);// ef.iot_device_live_state.Where(c => c.ls_d_guid == device.d_gw_d_guid && c.ls_live_state_set_time > dtOnline).FirstOrDefault();
                if (live_State == null)
                {
                    isPass = false;
                    new TaskPlainLog().addTaskPlianTaskLogItem(item, 1, "设备“" + device.d_name + "”-网关不在线");
                    break;
                    // return isPass;
                }
            }
            if (isPass == false)
            {
                new TaskPlainLog().addTaskPlianTaskLog(plain, 1, "检测异常，任务运行失败");
            }
            ef.Dispose();
            return isPass;
        }


    }
}
